<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace proxy;

use think\Exception;

class Client
{
    public const TYPE_CURL = 'Curl';

    public const RETURN_TYPE = 'Json';

    /**
     * @var mixed|string 请求类型
     */
    protected $type = '';

    /**
     * @var null|Curl 请求实例
     */
    protected ?Curl $client;

    public function __construct()
    {
        $this->type = env('proxy.type', 'Curl');
    }

    /**
     * POST请求.
     *
     * @param string $serviceName 服务名
     * @param string $url 请求连接
     * @param array $data 请求数据
     * @param mixed $timeout 超时时间
     * @return $this
     * @throws Exception
     */
    public function post(string $serviceName = '', string $url = '', array $data = [], $timeout = 0): Client
    {
        $this->client = $this->getClient();
        $this->client->post($serviceName, $url, $data);
        return $this->setTimeout($timeout);
    }

    /**
     * POST请求.
     *
     * @param string $serviceName 服务名
     * @param string $url 请求连接
     * @param array $data 请求数据
     * @param mixed $timeout 超时时间
     * @return $this
     * @throws Exception
     */
    public function postJson(string $serviceName = '', string $url = '', array $data = [], $timeout = 0): Client
    {
        $this->client = $this->getClient();
        $this->client->postJson($serviceName, $url, $data);
        return $this->setTimeout($timeout);
    }

    /**
     * GET请求.
     *
     * @param string $serviceName 服务名
     * @param string $url 请求连接
     * @param array $data 请求数据
     * @param mixed $timeout 超时时间
     * @return $this
     * @throws Exception
     */
    public function get(string $serviceName = '', string $url = '', array $data = [], $timeout = 0): Client
    {
        $this->client = $this->getClient();
        $this->client->get($serviceName, $url, $data);
        return $this->setTimeout($timeout);
    }

    /**
     * GET请求.
     *
     * @param string $serviceName 服务名
     * @param string $url 请求连接
     * @param array $data 请求数据
     * @param mixed $timeout 超时时间
     * @return $this
     * @throws Exception
     */
    public function getJson(string $serviceName = '', string $url = '', array $data = [], $timeout = 0): Client
    {
        $this->client = $this->getClient();
        $this->client->getJson($serviceName, $url, $data);
        return $this->setTimeout($timeout);
    }

    /**
     * 设置请求头.
     *
     * @throws Exception
     */
    public function setHeader(array $headers = []): Client
    {
        if ($this->client->setHeader($headers)) {
            return $this;
        }
        throw new Exception('请求头设置失败');
    }

    /**
     * 设置调用超时时间.
     *
     * @param mixed $timeout
     * @throws Exception
     */
    public function setTimeout($timeout = 30): Client
    {
        if (! $timeout) {
            $timeout = intval(env('proxy.timeout', 30));
        }

        if ($this->client->setTimeout($timeout)) {
            return $this;
        }
        throw new Exception('超时时间设置失败');
    }

    /**
     * 执行请求.
     *
     * @param mixed $type
     * @return bool|mixed|string
     * @throws Exception
     */
    public function exec($type = 'Json')
    {
        $res = $this->client->exec();
        if ($type == self::RETURN_TYPE) {
            return json_decode($res, true);
        }
        return $res;
    }

    /**
     * 获取客户端实例.
     * @return Curl
     * @throws Exception
     */
    protected function getClient(): ?Curl
    {
        if ($this->type == self::TYPE_CURL) {
            return (new Curl())->setHandle();
        }
        throw new Exception('未知请求类型');
    }
}
